#ifndef TABLE_H
#define TABLE_H

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;

template<typename T, int Num> class InterpConditions;
 
template<typename T, int Num> ostream & operator<<(ostream & os, const InterpConditions<T,Num> &IC);

// T为插入数据的类型，Num为表的行数-1（初始索引值为0）
template<typename T, int Num>
class InterpConditions
{
 private:
  vector<vector<T> > Table_;
  vector<vector<bool> > BoolTable_;
 public:
  InterpConditions();
  InterpConditions(const vector<vector<T> >& tab, const vector<vector<bool> >& booltab);
  InterpConditions(const string &_file);
  ~InterpConditions();
    
  void setTable(const vector<vector<T> >& tab, const vector<vector<bool> >& booltab);
  void setTableByFile(const string &_file);
  const vector<vector<T> >& getTable() const;
  const vector<vector<bool> >& getBoolTable() const;
  friend ostream& operator<< <T> (ostream& os, const InterpConditions<T,Num>& IC);
};


template<typename T, int Num>
InterpConditions<T,Num>::InterpConditions()
{};
    
template<typename T, int Num>
InterpConditions<T,Num>::InterpConditions(const vector<vector<T> >& tab, const vector<vector<bool> >& booltab)
{
  setTable(tab,booltab);
}

template<typename T, int Num>
InterpConditions<T,Num>::InterpConditions(const string &_file)
{
  setTableByFile(_file);
}
  
template<typename T, int Num>
InterpConditions<T,Num>::~InterpConditions()
{};

template<typename T, int Num>
void InterpConditions<T,Num>::setTable(const vector<vector<T> >& tab, const vector<vector<bool> >& booltab)
{
    if (tab.size() != Num+1 || booltab.size() != Num+1)
    {
    cerr << "Error! Size of table do not match." << endl;
    exit(-1);
    }
  else{
    Table_ = tab;
    BoolTable_ = booltab;
  }
}

template<typename T, int Num>
void InterpConditions<T,Num>::setTableByFile(const string &_file)
{
    std::fstream data(_file);
    // x,y分别为表的行数和列数
    int x,y;
    data >> x >> y;
    if (x != Num+1 || y < 1){
      cerr << "Error! Size of table do not match." << endl;
      data.close();
      exit(-1);
    }
    else{ // '&'代表该处数据缺失
      vector<vector<T> > tab;
      vector<T> Tvec(y,0);
      vector<vector<bool> > booltab;
      vector<bool> boolvec(y,1);
      for (int i = 0 ; i < x ; i++){
        Tvec.clear();
        Tvec.resize(y,0);
        boolvec.clear();
        boolvec.resize(y,1);
        for (int j = 0 ; j < y ; j++){
           char c[20];
           data >> c;
           if (c[0] == '&')
             boolvec[j] = 0;
           else
             Tvec[j] = atof(c);
        }
        tab.push_back(Tvec);
        booltab.push_back(boolvec);
      }
      data.close();
      setTable(tab,booltab);
    }
}

template<typename T, int Num>
const vector<vector<T> >& InterpConditions<T,Num>::getTable() const
{
  return Table_;
}
    
    
template<typename T, int Num>
const vector<vector<bool> >& InterpConditions<T,Num>::getBoolTable() const
{
  return BoolTable_;
}

// 输出表
template<typename T, int Num>
ostream& operator<<(ostream& os, const InterpConditions<T,Num>& IC)
{
  vector<vector<T> > Ttab = IC.getTable();
  vector<vector<bool> > booltab = IC.getBoolTable();
  const int x = Ttab.size();
  const int y = Ttab[0].size();
  os << x << " " << y << endl;
  for (int i = 0 ; i < x ; i++){
    for (int j = 0 ; j < y ; j++){
      if (booltab[i][j] == 1)
        os << Ttab[i][j] << " ";
      else
        os << "& ";
    }
    os << "\b" << endl;  // 消除空格
  }
  return os;  
}


#else
//do nothing
#endif
